﻿using Jermaine;
using Jermaine.Cache;
using Jermaine.Serialization;
using Jermaine.Task;
using Jermaine.UI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Dynamic;
using Jermaine.Dynamic;
using Jermaine.Extensions;
using Jermaine.Encrypt;
using System.Windows.Forms;
namespace Test
{
    class Program
    {
        [STAThread]
        static void Main(string[] args) {
            //TestCache();

            ISerializer s = SerializerFactory.GetSerializer<JsonSerializer>();
            var o = new Model { A = "a", B = "b", Version = new Version("1.0.0") };
            var ss = s.Format<Model>(o);
            Console.WriteLine(ss);
            Console.WriteLine(s.Parse<Model>(ss));
            //Console.WriteLine(t.BaseType);
            //Application.EnableVisualStyles();
            //WindowHide.SetTrayIconVisible("电脑管家实时防护", false);
            //var str = s.Format<Model>(o);
            //Console.WriteLine( Convert.ToBase64String(System.Text.Encoding.Default.GetBytes(str)));
            //Model o1 = s.Parse<Model>(str);
            //Console.WriteLine(o.Get());
            //Console.WriteLine(Object.ReferenceEquals(o,o1));
            //var x= "FFFF1010ABCD";
            //var bytes = StringHelper.HexStringToBytes(x);
            //x = StringHelper.BytesToHexString(bytes);
            //Console.WriteLine(x);
            //o = new Model2();
            //str = s.Format<Model2>(o);
            //Console.WriteLine(Convert.ToBase64String(System.Text.Encoding.Default.GetBytes(str)));
            //o = s.Parse<Model2>(str);
            //Console.WriteLine(o.Get());
            //Console.Read();
            //TestCache();
            //Test();
            //var model = new Model { A = "aaa", B = "bbb" };
            ////Console.WriteLine(model.Get<string>("A"));
            //var model2 = new Model { A = "aa", B = "xxx" };
            //ExpandoObject xs = new ExpandoObject();

            //var dict = new Dictionary<string, object> {
            //    {"Name","Test"},
            //    {"TestFunc",new Func<int, int, int>((x, y) => { return x + y; })},
            //    {"Age",12},
            //    {"Func",new Action(TestTask)}
            //};
            //dynamic o = DynamicProxy.Extend(dict);
            //o.Test = "Testsss";

            TestTask();
            ////TestReflector();
            ////var list = new List<Model>();
            ////list.Add(model); list.Add(model2);
            ////var dic = list.ToDictionary<Model, string>(o => {
            ////    return o.A;
            ////});

            ////dynamic oo = new ExpandoObject();
            ////oo.Action = new Func<int, int, int>((x, y) => { return x + y; });
            ////Console.WriteLine(oo.Action(10, 9));

            ////Console.WriteLine(((Func<int, int, int>)((IDictionary<string, object>)oo)["Action"])(10, 9));
            ////var o = new D_NewsInfo();
            ////dynamic i = 1;
            ////o.T(i);
            ////
            ////ExpandoObject xo = new ExpandoObject();
            //Console.WriteLine(o.Name);
            //Console.WriteLine(o.TestFunc(1, 2));
            //Console.WriteLine(o.Age);
            //Console.WriteLine(o.Test);
            //o.Func();
            //var e = EncryptFactory.GetInstance<DESEncrypt>();
            //var text = "13781900";
            //var result = e.Encrypt(text);
            //Console.WriteLine(result);
            //Console.WriteLine(e.Decrypt(result));
            //Console.WriteLine(Encrypt.Md5(text));
            //Console.WriteLine(Encrypt.Sha1(text));
            //var model = new Model();
            //model.Use(o => o.A = "a")
            //    .Use(o => o.C = "name")
            //    .Use(o => {
            //        Console.WriteLine(o.ToString());
            //    });
            //model.ToJson();
            //Console.WriteLine(typeof(IList<>));
            //TestDict();
            //SmartConsole.Initialize();


            //typeof(System.Windows.Forms.ComboBox).GetProperties(BindingFlags.FlattenHierarchy).Ext(p => {
            //    foreach (var item in p) {
            //        Console.WriteLine(item.Name);
            //    }
            //});
            Console.Read();

        }



        static void Execute(int x, int y, Action<int, int> action) {
            foreach (var item in action.GetInvocationList()) {
                (item as Action<int, int>)(x, y);
            }
        }

        public static void TestDictionary() {
            var o = new Model();
            Console.WriteLine(o.Ext(p => p.A = "a").Ext(p => p.B = "b").ToString());


            Action<int, int> action = (x, y) => {
                Console.WriteLine("{0} + {1} = {2}", x, y, x + y);
            };
            action += (x, y) => {
                string r = string.Empty;
                if (x > y) { r = "大于"; } else if (x == y) { r = "等于"; } else { r = "小于"; }
                Console.WriteLine("{0} {1} {2}", x, r, y);
            };

            Execute(9, 4, action);
            var dict = new Dictionary<string, int> {
                {"1",1},
                {"2",2},
                {"3",3}
            };

            dict.Lambda(value => value * 2);
            dict.ForEach((key, value) => {
                Console.WriteLine(value);
            });
        }

        public class NewsInfo
        {
            private Int32 _id = 0;
            private String _title = String.Empty;

            public NewsInfo() { }
            public NewsInfo(Int32 id, String title) {
                this._id = id;
                this._title = title;
            }
            public Int32 id {
                get { return this._id; }
                set { this._id = value; }
            }
            /// <summary>
            /// 标题
            /// </summary>
            public String Title {
                get { return this._title; }
                set { this._title = value; }
            }

            public NewsInfo this[int index] {
                get { return null; }
                set { throw new NotImplementedException(); }
            }

            public void T(object o) {
                Console.WriteLine("object");
            }

            public void T(int i) {
                Console.WriteLine("int");
            }
        }



        public static void TestReflector() {
            //D_NewsInfo o = new D_NewsInfo(11, "测试");
            //PropertyInfo[] p = o.GetType().GetProperties();
            //foreach (PropertyInfo item in p) {
            //    Console.WriteLine(item.Name + " - " + item.GetValue(o, null));
            //}
            var model = new Model { A = "aaa", B = "bbb" };
            Reflector.SetPropertyValue<string>(model, 1, "111");
            Reflector.Call<Model>("Test");
            Console.WriteLine(Reflector.Call<String>(model, "ToString"));
            Reflector.SetFieldValue<Model, string>(model, "C", "cccc");
            Console.WriteLine(Reflector.GetFieldValue<Model, string>(model, "C"));
            Console.WriteLine(model);
            Console.WriteLine(Reflector.Call<string>(typeof(Model), "Get"));
            foreach (var item in Reflector.GetProperties<Model>()) {
                Console.WriteLine(item.Name);
                Console.WriteLine(Reflector.GetPropertyValue<string>(model, item.Name));
            }
        }

        public static void TestCache() {

            var cache = CacheFactory.Default;
            cache.ItemAdded += cache_ItemAdded;
            cache.ItemRemoved += cache_ItemRemoved;
            cache.ItemUpdated += cache_ItemUpdated;

            cache.Put<Model>("mm", new Model { A = "aaa", B = "bbb" });

            //Thread.Sleep(2000);
            Console.WriteLine(cache.Get<Model>("mm"));
            cache.Put<Model>("mm", new Model { A = "bb", B = "aa" });
            //Thread.Sleep(2000);
            Console.WriteLine(cache.Get<Model>("mm"));



            var random = new Random();

            UIInvoker.RunBackgroundWork(() => {
                while (true) {
                    var id = Guid.NewGuid().ToString();
                    var item = id;
                    var time = new ExpiredTime(DateTime.Now.AddSeconds(random.Next(0, 10)));
                    cache.Put<string>(id, item, time);
                    var t = random.Next(1, 12);
                    Thread.Sleep(t * 100);
                }



            });
            UIInvoker.RunBackgroundWork(() => {
                while (true) {
                    var id = Guid.NewGuid().ToString();
                    var item = id;
                    var time = new ExpiredTime(DateTime.Now.AddSeconds(random.Next(0, 5)));
                    cache.Put<string>(id, item, time);
                    var t = random.Next(1, 7);
                    Thread.Sleep(t * 100);
                }



            });
            UIInvoker.RunBackgroundWork(() => {
                while (true) {
                    var id = Guid.NewGuid().ToString();
                    var item = id;
                    var time = new ExpiredTime(DateTime.Now.AddSeconds(random.Next(0, 3)));
                    cache.Put<string>(id, item, time);
                    var t = random.Next(1, 9);
                    Thread.Sleep(t * 100);
                }



            });
            UIInvoker.RunBackgroundWork(() => {
                while (true) {
                    var id = Guid.NewGuid().ToString();
                    var item = id;
                    var time = new ExpiredTime(DateTime.Now.AddSeconds(random.Next(0, 8)));
                    cache.Put<string>(id, item, time);
                    var t = random.Next(1, 9);
                    Thread.Sleep(t * 100);
                }


            });


        }

        class Task : ITask
        {

            public object Result {
                get;
                set;
            }

            public void Execute() {
                var random = new Random();
                Console.WriteLine(Name + random.Next());
            }

            public object Data {
                get;
                set;
            }

            public string Name {
                get {
                    return "测试你好";
                }
                set {
                    throw new NotImplementedException();
                }
            }
        }

        static void TestTask() {
            var f = TaskFactory.Create();
            f.Start();
            List<string> list = new List<string>();
            var random = new Random();
            UIInvoker.RunBackgroundWork(() => {
                while (true) {
                    var id = Guid.NewGuid().ToString();
                    f.Put(new Action(() => {
                        Console.WriteLine(id);
                    }));
                    Thread.Sleep(random.Next(1, 10) * 100);
                }
            });

            UIInvoker.RunBackgroundWork(() => {
                while (true) {

                    f.Put(new Task());
                    Thread.Sleep(random.Next(1, 10) * 100);
                }
            });

            Thread.Sleep(10*60*1000);

            f.Terminate();
        }

        static void Test() {
            string test = "abcdefghijklmnopqrstuvwxyz";

            // To retrieve the value of the indexed Chars property using
            // reflection, first get a PropertyInfo for Chars.
            PropertyInfo pinfo = typeof(string).GetProperty("Chars");

            // To retrieve an instance property, the GetValue method
            // requires the object whose property is being accessed and an
            // array of objects representing the index values.

            // Show the seventh letter (g)
            object[] indexArgs = { 6 };
            object value = pinfo.GetValue(test, indexArgs);

            Console.WriteLine(value);

            // Show the complete string.
            for (int x = 0; x < test.Length; x++) {
                Console.Write(pinfo.GetValue(test, new Object[] { x }));
            }
        }

        static void cache_ItemUpdated(object sender, CacheItemEventArgs e) {
            Log.Default.Info(string.Format("Update id:{0} time:{1} count:{2} item:{3}", e.Id, e.Time, e.ItemCount, e.NewItem));
            Console.WriteLine("Update id:{0} time:{1}", e.Id, e.Time);
            Console.WriteLine("Count:{0} {1}", e.ItemCount, e.NewItem);
        }

        static void cache_ItemRemoved(object sender, CacheItemEventArgs e) {
            SmartConsole.Write(string.Format("Remove id:{0} time:{1} count:{2} item:{3}", e.Id, e.Time, e.ItemCount, e.OldItem));
            Log.Default.Info(string.Format("Remove id:{0} time:{1} count:{2} item:{3}", e.Id, e.Time, e.ItemCount, e.OldItem));
            Console.WriteLine("Remove id:{0} time:{1}", e.Id, e.Time);
            Console.WriteLine("Count:{0}-item:{1}", e.ItemCount, e.NewItem);
        }

        static void cache_ItemAdded(object sender, CacheItemEventArgs e) {
            Log.Default.Info(string.Format("Add id:{0} time:{1} count:{2} item:{3}", e.Id, e.Time, e.ItemCount, e.NewItem));
            Console.WriteLine("Add id:{0} time:{1}", e.Id, e.Time);
            Console.WriteLine("Count:{0}-item:{1}", e.ItemCount, e.NewItem);
        }
    }
}
